﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;

namespace StockholmsStad.Web.UI.Class.Utilities
{
    /// <summary>
    /// Utilityfunktioner för att hantera (listor av) datum och tider. 
    /// </summary>
    public class DateTimeUtil
    {
        /// <summary>
        /// Plockar fram de första tiderna ur en lista av tider. ListItem har alltid datumets Ticks som värde.
        /// </summary>
        /// <param name="nrOfItems"></param>
        /// <param name="dates"></param>
        /// <param name="GetDateTimeText">Formateringsfunktion för Text-värdet i ListItem</param>
        /// <returns></returns>
        public static ListItem[] GetFirstListItems(int nrOfItems, IEnumerable<DateTime> dates,
                                                   Func<DateTime, string> GetDateTimeText)
        {
            return GetFirstListItemsImpl(dates, nrOfItems, GetDateTimeText, null);
        }

        ///<summary>
        /// Plockar fram de första dagarna ur en lista av tider. ListItem har alltid datumets Ticks som värde.
        ///</summary>
        ///<param name="nrOfItems"></param>
        ///<param name="dates"></param>
        ///<param name="GetDateTimeText"></param>
        ///<returns></returns>
        public static ListItem[] GetFirstDatesListItems(int nrOfItems, IEnumerable<DateTime> dates,
                                                        Func<DateTime, string> GetDateTimeText)
        {
            IEqualityComparer<DateTime> dateComparer = new DateOnlyComparer();
            return GetFirstListItemsImpl(dates, nrOfItems, GetDateTimeText, dateComparer);
        }

        private static ListItem[] GetFirstListItemsImpl(IEnumerable<DateTime> dates, int nrOfItems,
                                                        Func<DateTime, string> GetDateTimeText,
                                                        IEqualityComparer<DateTime> dateComparer)
        {
            if (dates == null)
                return new ListItem[0];
            IEnumerable<DateTime> maxTenTimeblocks = dates.OrderBy(d => d.Ticks);
            if (dateComparer != null)
                maxTenTimeblocks = maxTenTimeblocks.Distinct(dateComparer);
            maxTenTimeblocks = maxTenTimeblocks.Take(nrOfItems);
            IEnumerable<ListItem> freeblocks =
                maxTenTimeblocks.Select(d => new ListItem(GetDateTimeText(d), d.Ticks.ToString()));
            ListItem[] array = freeblocks.ToArray();
            return array;
        }

        /// <summary>
        /// Tar fram det datum som matchar dag och år. Tid spelar ingen roll.
        /// </summary>
        /// <param name="date"></param>
        /// <param name="dates"></param>
        /// <returns></returns>
        public static DateTime? GetFirstYearAndDayMatch(DateTime date, IEnumerable<DateTime> dates)
        {
            DateTime? returnValue = (from d in dates
                                     where d.Year == date.Year && d.DayOfYear == date.DayOfYear
                                     select (DateTime?) d).FirstOrDefault();
            return returnValue;
        }

        /// <summary>
        /// Tar fram det tidigaste datumet ur en lista
        /// </summary>
        /// <param name="dates"></param>
        /// <returns></returns>
        public static DateTime? GetEarliestDate(IEnumerable<DateTime> dates)
        {
            return dates.OrderBy(d => d.Ticks).Select(d => (DateTime?) d).FirstOrDefault();
        }
    }

    internal class DateOnlyComparer : IEqualityComparer<DateTime>
    {
        #region IEqualityComparer<DateTime> Members

        public bool Equals(DateTime x, DateTime y)
        {
            return x.Year == y.Year && x.DayOfYear == y.DayOfYear;
        }

        public int GetHashCode(DateTime obj)
        {
            return obj.Year + obj.DayOfYear;
        }

        #endregion
    }
}